package com.zhtd.knocker.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public final class HttpImpl implements HttpExecutor {

    private ResponseBean getRes(Exception e) {
        ResponseBean res = new ResponseBean();
        String msg = "请求错误";
        if (e != null && e.getLocalizedMessage() != null) {
            msg += ":" + e.getLocalizedMessage();
        }
        res.setResponse(msg);
        res.setStatus(ResponseBean.Status.FAILED);
        return res;
    }

    private String getStreamValue(InputStream in) throws IOException {
        String streamValue = "";
        if (in != null) {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            byte[] b = new byte[4 * 1024];
            int read = -1;
            while ((read = in.read(b)) > 0) {
                bo.write(b, 0, read);
                bo.flush();
            }
            streamValue = new String(bo.toByteArray());
            closeIn(in);
            closeOut(bo);
        }
        return streamValue;
    }

    private ResponseBean getRes(HttpURLConnection conn) {
        ResponseBean res = new ResponseBean();
        try {
            int code = conn.getResponseCode();
            String stream = "";
            if (code == 200) {
                res.setStatus(ResponseBean.Status.SUCCESS);
                stream = getStreamValue(conn.getInputStream());
                res.setResponse(stream);
            } else {
                res.setStatus(ResponseBean.Status.FAILED);
                stream = getStreamValue(conn.getErrorStream());
                res.setResponse(String.format("%d:%s", code, stream));
            }
        } catch (Exception e) {
            String msg = "请求错误";
            if (e != null && e.getLocalizedMessage() != null) {
                msg += ":" + e.getLocalizedMessage();
            }
            res.setResponse(msg);
            res.setStatus(ResponseBean.Status.FAILED);
        } finally {
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    @Override
    public ResponseBean doGet(HttpRequest req) {
        ResponseBean res = null;
        try {
            URL url = new URL(req.getUrl());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", "application/x-json");
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(req.getConnectTimeout());
            conn.setReadTimeout(req.getReadTimeout());
            conn.connect();
            res = getRes(conn);
        } catch (Exception e) {
            res = getRes(e);
        }
        return res;
    }

    @Override
    public ResponseBean doPost(HttpRequest req) {
        ResponseBean res = null;
        try {
            URL url = new URL(req.getUrl());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(req.getConnectTimeout());
            conn.setReadTimeout(req.getReadTimeout());
            conn.connect();
            // 设置输入参数
            OutputStream out = conn.getOutputStream();
            String str = req.getBody();
            if (str != null) {
                byte[] buf = str.getBytes("utf-8");
                out.write(buf, 0, buf.length);
                out.flush();
            }
            res = getRes(conn);
            closeOut(out);
        } catch (Exception e) {
            res = getRes(e);
        }
        return res;
    }

    private void closeOut(OutputStream out) {
        if (out != null) {
            try {
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    private void closeIn(InputStream in) {
        if (in != null) {
            try {
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
